package com.jwgf.smarowindingmachine_unity.ui;

import android.graphics.Color;
import android.os.Bundle;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.Spinner;
import android.widget.TableLayout;
import android.widget.TableRow;
import android.widget.TextView;

import com.jwgf.common.ViewCache;
import com.jwgf.fault.FaultRecorder;
import com.jwgf.objectbox.FaultCounter;
import com.jwgf.objectbox.ProcessCounter;
import com.jwgf.objectbox.RedLightCounter;
import com.jwgf.objectbox.ShiftReport;
import com.jwgf.report.ShiftTimeRule;
import com.jwgf.smarowindingmachine_unity.R;
import com.jwgf.smarowindingmachine_unity.logic.Report;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.TimeUnit;

import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
import io.reactivex.rxjava3.core.Observable;
import io.reactivex.rxjava3.core.ObservableOnSubscribe;
import io.reactivex.rxjava3.core.Observer;
import io.reactivex.rxjava3.disposables.Disposable;
import io.reactivex.rxjava3.functions.Consumer;
import io.reactivex.rxjava3.functions.Function;
import io.reactivex.rxjava3.schedulers.Schedulers;

public class MachineStateSpindleStatisticFragment extends BaseFragment {
    public static final String fragmentTag = "MachineStateSpindleStatisticFragment";
    private final int COLUMN = 8;

    private TextView date;
    private TextView shift_num;
    private Spinner type_spinner;
    private TextView operator_tv;
    private TextView shift_team_tv;
    private Button head_btn;
    private Button prev_btn;
    private Button next_btn;
    private Button tail_btn;
    private TextView tvShiftInfoShow;
    private long totalRecord;
    private long currentRecord;

    private TableLayout table;
    private Button btnPrev;
    private Button btnNext;

    private View v;

    private ArrayList<String> typeList = new ArrayList<String>();

    private Calendar curDate = Calendar.getInstance();
    private int reportType = Report_Type.redLight;
    private int page = 0;

    private HashMap<Integer, TextView> cells = new HashMap<Integer, TextView>();

    List<RedLightCounter> redLightData;
    List<ProcessCounter> processData;
    List<FaultCounter> faultData;
    int dataSize;

    private boolean[] buttonStatus = {true, true, false, true};

    private Disposable disposable;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        v = ViewCache.getInstance().getView(R.layout.fragment_machine_state_spindle_statistic);
        curDate.setTimeInMillis(Long.valueOf(ShiftTimeRule.getInstance().getCurrentShiftStartTime()));
        initViews();
        rxRefresh(curDate.getTimeInMillis(), "=");
        disposable = Observable.interval(1, TimeUnit.MINUTES).observeOn(AndroidSchedulers.mainThread()).subscribe(new Consumer<Long>() {
            @Override
            public void accept(Long aLong) throws Exception {
                rxRefresh(curDate.getTimeInMillis(), "=");
            }
        });
        return v;
    }

    @Override
    public void onHiddenChanged(boolean hidden) {
        super.onHiddenChanged(hidden);
        if (hidden) {
            disposable.dispose();
        } else {
            rxRefresh(curDate.getTimeInMillis(), "=");
            disposable = Observable.interval(1, TimeUnit.MINUTES).observeOn(AndroidSchedulers.mainThread()).subscribe(new Consumer<Long>() {
                @Override
                public void accept(Long aLong) throws Exception {
                    rxRefresh(curDate.getTimeInMillis(), "=");
                }
            });
        }
    }

    private void initViews() {
        date = (TextView) v.findViewById(R.id.date);
        shift_num = (TextView) v.findViewById(R.id.shift_num);
        type_spinner = (Spinner) v.findViewById(R.id.type_spinner);
        operator_tv = (TextView) v.findViewById(R.id.operator_tv);
        shift_team_tv = (TextView) v.findViewById(R.id.shiftteam_tv);
        head_btn = (Button) v.findViewById(R.id.head_btn);
        prev_btn = (Button) v.findViewById(R.id.prev_btn);
        next_btn = (Button) v.findViewById(R.id.next_btn);
        tail_btn = (Button) v.findViewById(R.id.tail_btn);
        tvShiftInfoShow = (TextView) v.findViewById(R.id.tv_shift_show);
        currentRecord = Report.getInstance().getShiftCount();
        totalRecord = Report.getInstance().getShiftCount();

        table = (TableLayout) v.findViewById(R.id.table);
        table.setStretchAllColumns(true);
        table.setOrientation(LinearLayout.VERTICAL);
//        table.setDividerDrawable(getActivity().getResources().getDrawable(R.drawable.row_divider));
//        table.setShowDividers(LinearLayout.SHOW_DIVIDER_BEGINNING | LinearLayout.SHOW_DIVIDER_MIDDLE | LinearLayout.SHOW_DIVIDER_END);

        buildTable();

        btnPrev = (Button) v.findViewById(R.id.btn_prev_spindle);
        btnPrev.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                if (page > 0) {
                    --page;
                    switchPage();
                }
            }
        });
        btnNext = (Button) v.findViewById(R.id.btn_next_spindle);
        btnNext.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                if ((page + 1) * COLUMN < dataSize) {
                    ++page;
                    switchPage();
                }
            }
        });

        head_btn.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                rxRefresh(curDate.getTimeInMillis(), "<<");
            }
        });

        prev_btn.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                rxRefresh(curDate.getTimeInMillis(), "<");
            }
        });

        next_btn.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                rxRefresh(curDate.getTimeInMillis(), ">");
            }
        });

        tail_btn.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                rxRefresh(curDate.getTimeInMillis(), ">>");
            }
        });

        type_spinner.setAdapter(new ArrayAdapter<String>(getActivity(),
                android.R.layout.simple_dropdown_item_1line, getTypeData()));

        type_spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {

            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                TextView tv = (TextView) view;
                if (tv == null)
                    return;
                tv.setTextSize(10f);
                reportType = position;
                rxRefresh(curDate.getTimeInMillis(), "=");

            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {

            }
        });

    }

    private void setBtnState(boolean isEnable) {
        if (isEnable) {
            head_btn.setEnabled(buttonStatus[0]);
            prev_btn.setEnabled(buttonStatus[1]);
            next_btn.setEnabled(buttonStatus[2]);
            tail_btn.setEnabled(buttonStatus[3]);
        } else {
            head_btn.setEnabled(false);
            prev_btn.setEnabled(false);
            next_btn.setEnabled(false);
            tail_btn.setEnabled(false);
        }
    }

    private void rxRefresh(long time, String flag) {
        setBtnState(false);
        Observable<Long> observable = Observable.create((ObservableOnSubscribe<ShiftReport>) emitter -> {
            long sqlTime = Report.getInstance().getTime(time, flag);
            ShiftReport basicInfo = Report.getInstance().getBasicInfo(sqlTime);
            totalRecord = Report.getInstance().getShiftCount();
            switch (flag) {
                case "<<":
                    currentRecord = 1;
                    break;
                case "<":
                    if (currentRecord > 1)
                        --currentRecord;
                    break;
                case ">":
                    if (currentRecord < totalRecord)
                        ++currentRecord;
                    break;
                case ">>":
                    currentRecord = totalRecord;
                    break;
            }
            emitter.onNext(basicInfo);
            emitter.onComplete();
        })
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .map((Function<ShiftReport, Long>) shiftReport -> {
                    refreshBasicUI(shiftReport);
                    return shiftReport.start;
                })
                .observeOn(Schedulers.io())
                .map((Function<Long, Long>) aLong -> {
                    switch (reportType) {
                        case Report_Type.redLight:
                            redLightData = Report.getInstance().getRedLightLog(aLong);
                            dataSize = redLightData.size();
                            break;
                        case Report_Type.process:
                            processData = Report.getInstance().getProcessLog(aLong);
                            dataSize = processData.size();
                            break;
                        case Report_Type.fault:
                            faultData = Report.getInstance().getFaultLog(aLong);
                            dataSize = faultData.size();
                            break;
                    }
                    return aLong;
                })
                .observeOn(AndroidSchedulers.mainThread());

        Observer<Long> observer = new Observer<Long>() {
            Disposable d;

            @Override
            public void onSubscribe(Disposable d) {
                this.d = d;
            }

            @Override
            public void onNext(Long aLong) {
                switchPage();
                setBtnState(true);
            }

            @Override
            public void onError(Throwable e) {
                if (d != null && !d.isDisposed()) {
                    d.dispose();
                }
            }

            @Override
            public void onComplete() {
                if (d != null && !d.isDisposed()) {
                    d.dispose();
                }
            }
        };
        observable.subscribe(observer);
    }

    private List<String> getTypeData() {
        typeList.clear();
        String[] type = getResources().getStringArray(R.array.warning_type);
        for (String fault : type) {
            typeList.add(fault);
        }
        return typeList;
    }

    private void refreshBasicUI(ShiftReport shiftReport) {
        curDate.setTimeInMillis(shiftReport.start);
        SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
        String strDate = sf.format(curDate.getTime());
        String num = String.valueOf(shiftReport.shiftNum);
        String strOperator = shiftReport.operator;
        String strShiftTeam = shiftReport.team;
        totalRecord = Report.getInstance().getShiftCount();
        date.setText(strDate);
        shift_num.setText(num + getResources().getString(R.string.ms_shift));
        shift_team_tv.setText(strShiftTeam);
        operator_tv.setText(strOperator);
        tvShiftInfoShow.setText(currentRecord + "/" + totalRecord);

        if (currentRecord == 1) {
            buttonStatus[0] = true;
            buttonStatus[1] = false;
            buttonStatus[2] = true;
            buttonStatus[3] = true;
        } else if (currentRecord == totalRecord) {
            buttonStatus[0] = true;
            buttonStatus[1] = true;
            buttonStatus[2] = false;
            buttonStatus[3] = true;
        } else {
            buttonStatus[0] = true;
            buttonStatus[1] = true;
            buttonStatus[2] = true;
            buttonStatus[3] = true;
        }
    }

    private void buildTable() {
        for (int row = 0; row < 16; row++) {
            TableRow tableRow = new TableRow(getActivity());
//            tableRow.setDividerDrawable(getActivity().getResources().getDrawable(R.drawable.column_divider));
//            tableRow.setShowDividers(LinearLayout.SHOW_DIVIDER_MIDDLE);
            for (int col = 0; col < COLUMN + 1; col++) {
                TextView tv = new TextView(getActivity());
                tv.setTextSize(12f);
                tv.setTextColor(getResources().getColor(R.color.black));
                tv.setGravity(Gravity.CENTER);
                tableRow.addView(tv);
                cells.put(row * (COLUMN + 1) + col, tv);
            }
            table.addView(tableRow, new ViewGroup.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
            TableRow tableRowLine = new TableRow(getActivity());
            TextView line = new TextView(getActivity());
            line.setBackgroundColor(Color.rgb(0, 0, 0));
            line.setHeight(1);
            tableRowLine.addView(line);
            TableRow.LayoutParams params = (TableRow.LayoutParams) line.getLayoutParams();
            params.span = COLUMN + 1;
            line.setLayoutParams(params);
            table.addView(tableRowLine, new ViewGroup.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
        }
    }

    private void switchPage() {
        switch (reportType) {
            case Report_Type.redLight:
                for (int i = 0; i <= COLUMN; ++i) {
                    refreshColumnRedLight(redLightData, i);
                }
                break;
            case Report_Type.process:
                for (int i = 0; i <= COLUMN; ++i) {
                    refreshColumnProcess(processData, i);
                }
                break;
            case Report_Type.fault:
                for (int i = 0; i <= COLUMN; ++i) {
                    refreshColumnFault(faultData, i);
                }
                break;
        }

    }

    private void refreshColumnRedLight(List<RedLightCounter> list, int column) {
        if (column == 0) {
            HashMap<String, String> map = new HashMap<>();
            map.put("row1", FaultRecorder.getInstance().getFault(0x630100));
            map.put("row2", FaultRecorder.getInstance().getFault(0x630101));
            map.put("row3", FaultRecorder.getInstance().getFault(0x630102));
            map.put("row4", FaultRecorder.getInstance().getFault(0x630103));
            map.put("row5", FaultRecorder.getInstance().getFault(0x630104));
            map.put("row6", FaultRecorder.getInstance().getFault(0x63010F));

            for (int row = 0; row < 16; ++row) {
                cells.get(row * (COLUMN + 1) + column).setText(map.get("row" + row));
            }
        } else {
            if ((page * COLUMN + column - 1) < list.size()) {
                RedLightCounter counter = list.get(page * COLUMN + column - 1);
                HashMap<String, String> map = new HashMap<>();
                map.put("row0", counter.type);
                map.put("row1", String.valueOf(counter.count63DC0));
                map.put("row2", String.valueOf(counter.count63DC1));
                map.put("row3", String.valueOf(counter.count63DC2));
                map.put("row4", String.valueOf(counter.count63DC3));
                map.put("row5", String.valueOf(counter.count63DC4));
                map.put("row6", String.valueOf(counter.count63DC15));
                for (int row = 0; row < 16; ++row) {
                    cells.get(row * (COLUMN + 1) + column).setText(map.get("row" + row));
                }
            } else {
                for (int row = 0; row < 16; ++row) {
                    cells.get(row * (COLUMN + 1) + column).setText("");
                }
                return;
            }
        }
    }

    private void refreshColumnProcess(List<ProcessCounter> list, int column) {
        if (column == 0) {
            HashMap<String, String> map = new HashMap<>();
            map.put("row1", FaultRecorder.getInstance().getFault(0x630000));
            map.put("row2", FaultRecorder.getInstance().getFault(0x630001));
            map.put("row3", FaultRecorder.getInstance().getFault(0x630002));
            map.put("row4", FaultRecorder.getInstance().getFault(0x630003));
            map.put("row5", FaultRecorder.getInstance().getFault(0x630004));
            map.put("row6", FaultRecorder.getInstance().getFault(0x630005));
            map.put("row7", FaultRecorder.getInstance().getFault(0x630006));
            map.put("row8", FaultRecorder.getInstance().getFault(0x630007));
            map.put("row9", FaultRecorder.getInstance().getFault(0x630008));
            map.put("row10", FaultRecorder.getInstance().getFault(0x630009));
            map.put("row11", FaultRecorder.getInstance().getFault(0x63000A));
            map.put("row12", FaultRecorder.getInstance().getFault(0x63000B));

            for (int row = 0; row < 16; ++row) {
                cells.get(row * (COLUMN + 1) + column).setText(map.get("row" + row));
            }
        } else {
            if ((page * COLUMN + column - 1) < list.size()) {
                ProcessCounter counter = list.get(page * COLUMN + column - 1);
                HashMap<String, String> map = new HashMap<>();
                map.put("row0", counter.type);
                map.put("row1", String.valueOf(counter.count63DB0));
                map.put("row2", String.valueOf(counter.count63DB1));
                map.put("row3", String.valueOf(counter.count63DB2));
                map.put("row4", String.valueOf(counter.count63DB3));
                map.put("row5", String.valueOf(counter.count63DB4));
                map.put("row6", String.valueOf(counter.count63DB5));
                map.put("row7", String.valueOf(counter.count63DB6));
                map.put("row8", String.valueOf(counter.count63DB7));
                map.put("row9", String.valueOf(counter.count63DB8));
                map.put("row10", String.valueOf(counter.count63DB9));
                map.put("row11", String.valueOf(counter.count63DB10));
                map.put("row12", String.valueOf(counter.count63DB11));
                for (int row = 0; row < 16; ++row) {
                    cells.get(row * (COLUMN + 1) + column).setText(map.get("row" + row));
                }
            } else {
                for (int row = 0; row < 16; ++row) {
                    cells.get(row * (COLUMN + 1) + column).setText("");
                }
                return;
            }
        }
    }

    private void refreshColumnFault(List<FaultCounter> list, int column) {
        if (column == 0) {
            HashMap<String, String> map = new HashMap<>();
//            map.put("row1", FaultRecorder.getInstance().getFault(0x630105));
            map.put("row1", FaultRecorder.getInstance().getFault(0x630106));
            map.put("row2", FaultRecorder.getInstance().getFault(0x630107));
            map.put("row3", FaultRecorder.getInstance().getFault(0x630108));
            map.put("row4", FaultRecorder.getInstance().getFault(0x630109));
            map.put("row5", FaultRecorder.getInstance().getFault(0x63010A));
            map.put("row6", FaultRecorder.getInstance().getFault(0x63010B));
            map.put("row7", FaultRecorder.getInstance().getFault(0x63010C));
            map.put("row8", FaultRecorder.getInstance().getFault(0x63010D));
            map.put("row9", FaultRecorder.getInstance().getFault(0x63010E));
//            map.put("row11", FaultRecorder.getInstance().getFault(0x630200));
            map.put("row10", FaultRecorder.getInstance().getFault(0x630201));
            map.put("row11", FaultRecorder.getInstance().getFault(0x630203));
            map.put("row12", FaultRecorder.getInstance().getFault(0x630204));
//            map.put("row13", FaultRecorder.getInstance().getFault(0x63000C));

            for (int row = 0; row < 16; ++row) {
                cells.get(row * (COLUMN + 1) + column).setText(map.get("row" + row));
            }
        } else {
            if ((page * COLUMN + column - 1) < list.size()) {
                FaultCounter counter = list.get(page * COLUMN + column - 1);
                HashMap<String, String> map = new HashMap<>();
                map.put("row0", counter.type);
//                map.put("row1", String.valueOf(counter.count63DC5));
                map.put("row1", String.valueOf(counter.count63DC6));
                map.put("row2", String.valueOf(counter.count63DC7));
                map.put("row3", String.valueOf(counter.count63DC8));
                map.put("row4", String.valueOf(counter.count63DC9));
                map.put("row5", String.valueOf(counter.count63DC10));
                map.put("row6", String.valueOf(counter.count63DC11));
                map.put("row7", String.valueOf(counter.count63DC12));
                map.put("row8", String.valueOf(counter.count63DC13));
                map.put("row9", String.valueOf(counter.count63DC14));
//                map.put("row11", String.valueOf(counter.count63DD0));
                map.put("row10", String.valueOf(counter.count63DD1));
                map.put("row11", String.valueOf(counter.count63DD3));
                map.put("row12", String.valueOf(counter.count63DD4));
//                map.put("row13", String.valueOf(counter.count63DB12));

                for (int row = 0; row < 16; ++row) {
                    cells.get(row * (COLUMN + 1) + column).setText(map.get("row" + row));
                }
            } else {
                for (int row = 0; row < 16; ++row) {
                    cells.get(row * (COLUMN + 1) + column).setText("");
                }
                return;
            }
        }
    }

    public interface Report_Type {
        int redLight = 0;
        int process = 1;
        int fault = 2;
    }


}